Appearance
Codex Plan 模式实战:复杂需求为什么不要直接让 AI 写代码
前面几篇我们已经介绍了:
text
Codex CLI
AGENTS.md
常用命令
Prompt到了这里,已经可以把一个比较完整的任务交给 Codex。
例如:
text
给用户表增加一个 nickname 字段,
补充对应 DTO 和查询接口,
修改完成后运行相关测试。这种需求通常比较简单。
Codex 可以:
text
阅读代码
↓
找到相关文件
↓
修改代码
↓
运行测试但是如果需求变成:
text
把现在的余额系统增加“冻结余额”能力,
同时保证充值、提现、转账和奖励逻辑不受影响。情况就完全不同了。
因为这个需求背后可能涉及:
text
数据库
余额模型
钱包流水
提现
转账
事务
并发
幂等
旧接口兼容
历史数据如果直接告诉 Codex:
text
帮我实现。它可能很快就开始修改代码。
问题是:
text
它真的已经理解整个影响范围了吗?这就是复杂任务为什么需要:
text
Plan First也就是:
先规划,再实现。
1. 什么是 Plan?
Plan 可以简单理解成:
text
在修改代码之前,
先把这个任务想清楚。完整过程更接近:
text
Requirement
↓
Read
↓
Understand
↓
Explore
↓
Plan
↓
Confirm
↓
Implement
↓
Test
↓
Review而不是:
text
Requirement
↓
Write CodePlan 阶段最重要的特点是:
text
先不修改代码Codex 当前的任务主要是:
text
阅读
搜索
分析
推理
设计等方案明确以后,再进入:
text
Implement2. Plan 和 /plan 不是完全一回事
这里需要先区分两个概念。
第一个是:
text
Plan也就是:
text
规划阶段第二个是:
text
/plan也就是某个 Codex CLI 版本可能提供的具体交互入口或协作方式。
Codex CLI 仍然在持续更新。
不同版本中:
text
Plan
Collaboration Mode
Slash Command
交互入口可能发生变化。
因此当前版本到底提供什么命令,应该优先查看:
text
/help但无论当前版本有没有一个固定的:
text
/plan都不影响我们使用:
text
Plan First因为完全可以直接告诉 Codex:
text
先进入规划阶段。
阅读相关代码并给出实现方案。
当前阶段不要修改任何文件。本质上就是:
text
Plan3. 为什么不能复杂需求一上来就 Implement?
假设需求是:
text
增加用户余额冻结功能。如果直接:
text
帮我实现用户余额冻结功能。Codex 可能看到:
text
user_balance然后马上设计:
text
balance
frozen_balance接着修改:
text
Entity
Mapper
Service
SQL表面上看:
text
功能实现了但真实业务可能还有:
text
提现应该扣 available 还是 balance?
转账时冻结余额能不能使用?
冻结失败以后是否需要流水?
解冻是不是幂等?
一个订单能不能重复 freeze?
旧用户 frozen_balance 怎么初始化?
并发 freeze 是否可能超额冻结?
冻结和扣款之间是什么关系?如果这些问题没有先想清楚:
text
代码写得越快
风险反而越大4. Coding Agent 最大的问题不是不会写代码
现在的 Coding Agent 往往很擅长:
text
生成代码
修改多个文件
执行命令
修复编译错误真正困难的是:
text
它是否理解了正确的问题?如果问题理解错了:
text
高质量代码
+
错误方案
=
高质量地实现错误需求所以复杂任务中最重要的并不是:
text
让 Codex 快点写而是:
text
先确认它准备怎么写这就是 Plan 的价值。
5. 哪些任务建议先 Plan?
不是所有任务都需要。
例如:
text
修改变量名
修复拼写
增加 null 判断
增加简单 DTO 字段
补一个简单测试一般可以直接实现。
但下面这些任务,非常建议先 Plan:
text
架构调整
数据库结构修改
跨模块重构
支付逻辑
钱包逻辑
登录认证
权限系统
接口迁移
并发问题
数据一致性
性能优化
复杂线上 Bug
大型依赖升级可以用一个简单标准判断:
text
如果改错以后代价比较高
→ 先 Plan6. Plan 阶段到底应该做什么?
一个比较完整的 Plan 通常应该回答:
text
① 当前代码是怎么工作的?
② 需求会影响哪些模块?
③ 需要修改哪些文件?
④ 数据模型是否需要变化?
⑤ API 是否会变化?
⑥ 有没有兼容性问题?
⑦ 有没有事务和并发风险?
⑧ 有没有幂等问题?
⑨ 怎么测试?
⑩ 怎么判断实现完成?所以 Plan 不是:
text
列一个 TODO List而是:
text
建立完整的修改模型7. 第一步:先让 Codex 阅读现状
不要直接问:
text
这个功能应该怎么设计?最好先让 Codex:
text
理解当前实现例如:
text
分析当前用户余额系统。
先不要修改代码。
请找到:
1. 余额数据结构
2. 余额查询入口
3. 所有余额增加入口
4. 所有余额扣减入口
5. 钱包流水
6. 提现流程
7. 转账流程
8. 事务控制
9. 幂等机制
10. 相关测试
完成以后总结当前余额系统的完整调用关系。这一步可以叫:
text
Explore也就是:
text
探索代码8. 为什么 Explore 和 Plan 最好分开?
因为:
text
没有理解现状
就很难设计正确方案例如 Agent 一开始可能认为:
text
余额只在 UserBalanceService 修改但搜索以后发现:
text
充值
奖励
提现
转账
后台补单都存在不同入口。
这时候 Plan 自然会发生变化。
所以更可靠的流程是:
text
Explore
↓
建立事实
↓
Plan
↓
设计修改而不是:
text
猜测当前架构
↓
直接 Plan9. Plan 阶段要求 Codex 给出“证据”
这是一个非常实用的技巧。
不要只让 Codex说:
text
余额修改主要在 WalletService。可以要求:
text
说明判断依据。
列出:
- 文件
- 类
- 方法
- 调用关系例如:
text
请基于实际代码分析。
每个结论尽量指出:
文件
类名
方法名
如果无法从代码确认,
明确标记“未确认”,不要猜测。这样 Plan 会更可靠。
10. 第二步:分析影响范围
理解现状以后,再让 Codex回答:
text
这个需求会影响哪里?例如冻结余额功能:
text
请分析增加冻结余额以后可能影响的范围。
至少检查:
1. 余额查询
2. 提现
3. 内部转账
4. 充值
5. 奖励
6. 后台人工调整余额
7. 钱包流水
8. 定时任务
9. 数据统计
10. API 返回结构最终可能得到:
text
wallet
├── balance
├── transaction
├── withdraw
├── transfer
└── reward这一步叫:
text
Impact Analysis也就是:
text
影响分析11. 为什么影响分析很重要?
很多 Bug 并不是:
text
新代码本身写错而是:
text
新代码破坏了旧逻辑例如增加:
text
frozenBalance提现改了。
但是:
text
后台余额统计还在直接读取:
text
balance于是:
text
用户端余额
后台余额
财务余额出现不同结果。
这种问题只有在修改之前进行:
text
Impact Analysis才更容易发现。
12. 第三步:让 Codex 给出具体修改方案
完成 Explore 和 Impact Analysis 以后,再进入真正的 Plan。
例如:
text
基于刚才的分析,
给出实现用户余额冻结功能的方案。
要求:
1. 明确数据模型怎么修改
2. 明确 Service API
3. 明确 freeze 流程
4. 明确 unfreeze 流程
5. 明确最终扣款流程
6. 说明事务边界
7. 说明幂等方案
8. 说明并发控制
9. 说明旧数据兼容
10. 说明测试方案
列出预计需要修改的文件。
当前阶段仍然不要修改代码。注意最后一句:
text
仍然不要修改代码这样可以避免 Agent 在 Plan 过程中提前开始实施。
13. 一个好的 Plan 应该具体到什么程度?
太粗:
text
1. 修改数据库
2. 修改 Service
3. 增加测试这种 Plan 几乎没有意义。
比较好的 Plan 应该至少说明:
text
改什么
为什么改
在哪里改
怎么验证
有什么风险例如:
text
1. user_balance 增加 frozen_balance
原因:
需要区分可用余额和冻结余额。
兼容:
默认值为 0,保证历史用户数据兼容。
2. UserBalanceService 增加 freeze/unfreeze
freeze:
available balance 减少
frozen balance 增加
要求:
同一业务 sourceId 必须幂等。
3. WalletTransaction 增加 FREEZE / UNFREEZE 类型
用于记录冻结和解冻流水。
4. 增加并发测试
验证两个并发 freeze 不会导致 available balance < 0。这才是真正有实施价值的 Plan。
14. Plan 最重要的输出之一:文件清单
我非常推荐让 Codex 在 Plan 最后列出:
text
预计修改文件例如:
text
预计修改:
1. UserBalance.java
2. UserBalanceService.java
3. UserBalanceServiceImpl.java
4. WalletTransactionType.java
5. UserBalanceMapper.xml
6. V20260830__add_frozen_balance.sql
7. UserBalanceServiceTest.java为什么很有用?
因为你可以快速判断:
text
修改范围是不是合理?如果一个简单需求突然出现:
text
修改 37 个文件就应该检查:
text
是不是方案设计过度了?15. Plan 也是控制 Scope 的工具
上一篇讲 Prompt 时,我们介绍了:
text
ScopePlan 可以进一步验证 Scope。
例如你告诉 Codex:
text
只允许修改 wallet 模块。但 Plan 分析以后发现:
text
order 模块也依赖余额接口这时候 Codex 不应该偷偷修改:
text
order而应该告诉你:
text
当前 Scope 可能不足。
原因:
order 模块直接依赖旧余额行为。
建议:
扩大范围到 order,
或者保持旧接口兼容。这就是 Plan 的另一个价值:
text
在真正修改前暴露冲突16. 第四步:人工 Review Plan
Plan 生成以后:
text
不要马上回复“开始”先看几个重点。
是否理解需求?
例如你要:
text
冻结余额Agent 是否误解成:
text
锁定整个账户修改范围是否合理?
text
应该改 5 个文件
却准备改 30 个文件?有没有改变 API?
text
本来要求兼容
结果 Plan 准备删除旧字段?有没有引入新依赖?
text
现有能力能解决
却准备增加新框架?数据库方案是否安全?
text
有没有删除字段?
有没有修改历史 migration?测试是否覆盖关键风险?
text
并发
幂等
边界
异常Plan Review 本质上就是:
text
在代码产生之前做一次设计 Review17. 修改 Plan,而不是让 Codex 重新猜
如果 Plan 大体正确,但某些地方不满意,可以直接修改。
例如:
text
方案整体可以。
调整以下几点:
1. 不新增 Redis 分布式锁
2. 使用现有数据库乐观锁
3. 不新增 wallet_freeze 表
4. frozen_balance 直接放 user_balance
5. API 返回保持完全兼容
基于这些约束重新整理最终 Plan。
仍然不要修改代码。这比:
text
不行,重新想更有效。
因为你保留了:
text
已经正确的部分只调整:
text
有问题的决策18. 第五步:明确批准 Implement
Plan 确认以后,再告诉 Codex:
text
按最终方案实施。最好继续保留关键约束:
text
按最终 Plan 实施。
要求:
1. 只修改 Plan 中列出的文件
2. 如果实施过程中发现必须扩大范围,先停止并说明原因
3. 不修改现有 public API
4. 不新增第三方依赖
5. 不提交 Git
6. 修改完成后执行计划中的测试
7. 最后检查 git diff这时候 Codex 才正式进入:
text
Implement19. Implement 阶段不要让 Plan 失效
一个常见情况是:
text
Plan 很好但是实现过程中 Agent 发现新问题,然后开始:
text
自由发挥所以可以提前约定:
text
如果发现 Plan 与实际代码不一致:
不要自行扩大任务。
先说明:
1. 发现了什么
2. 为什么原 Plan 不成立
3. 建议怎么调整这个规则对于复杂项目非常有价值。
因为:
text
Plan不是为了做完以后好看。
而是为了:
text
控制实施过程20. 第六步:Test
代码修改完成以后,不要直接结束。
应该按照 Plan 中的验证方案执行:
text
Compile
↓
Unit Test
↓
Integration Test
↓
Git Diff例如:
text
完成实现以后:
1. 编译 wallet 模块
2. 运行 UserBalanceServiceTest
3. 运行提现相关测试
4. 运行转账相关测试
5. 检查 git diff如果测试失败:
text
Codex
↓
读取错误
↓
分析
↓
修复
↓
重新测试这才是完整 Agent Workflow。
21. Plan 阶段就应该设计测试
不要等代码写完才问:
text
应该测什么?因为测试本身也是设计的一部分。
例如冻结余额:
text
正常冻结
余额不足
重复冻结
正常解冻
重复解冻
并发冻结
冻结后提现
冻结后转账
异常回滚
历史用户 frozenBalance = 0如果 Plan 阶段已经列出这些测试:
text
实现方案往往也会更加完整。
因为测试会反过来暴露:
text
设计遗漏22. 第七步:Review
测试通过以后,继续:
text
Review 当前 Git Diff。例如:
text
Review 当前冻结余额功能的 Git Diff。
重点检查:
1. 是否存在超额冻结
2. 是否存在重复冻结
3. 是否存在重复解冻
4. 事务是否完整
5. 异常是否正确回滚
6. 钱包流水是否一致
7. 是否破坏旧 API
8. 是否存在 BigDecimal 精度问题
9. 是否有与当前需求无关的修改
不要修改代码,只输出 Review 结果。于是完整流程变成:
text
Explore
↓
Plan
↓
Plan Review
↓
Implement
↓
Test
↓
Code Review
↓
Developer Review23. 一个完整的 Plan Prompt 模板
下面这个模板可以直接保存:
text
任务:
<需求>
当前阶段只做分析和规划,
不要修改任何文件。
第一步:理解现状
请阅读相关代码并说明:
1. 当前实现
2. 主要调用链
3. 数据模型
4. 事务边界
5. 相关测试
第二步:影响分析
分析这个需求可能影响:
1. 模块
2. API
3. 数据库
4. 异步任务
5. 缓存
6. MQ
7. 兼容性
第三步:给出方案
请给出:
1. 实现思路
2. 数据结构变化
3. API 变化
4. 具体修改点
5. 并发和事务处理
6. 幂等方案
7. 兼容方案
8. 测试方案
9. 风险
最后列出:
预计修改的文件清单。
要求:
- 基于实际代码分析
- 无法确认的信息明确标记“未确认”
- 不要为了完成 Plan 而猜测
- 当前阶段不要修改代码24. Java / Spring Boot 重构 Plan 示例
假设需求:
text
把多个链 RPC Client 抽象成统一接口。可以:
text
分析当前链 RPC 实现。
目标:
将不同链的公共 RPC 能力抽象为 RpcClient。
当前阶段不要修改代码。
请:
1. 找到所有 RPC Client
2. 找到所有调用方
3. 对比不同 Client 的公共能力
4. 对比链特有能力
5. 分析当前依赖关系
6. 判断哪些方法适合进入 RpcClient
7. 判断哪些逻辑应该保留在具体实现
8. 分析是否需要 RpcClientHolder / Factory
9. 分析异常模型是否需要统一
10. 分析现有调用方的迁移成本
给出最终接口设计。
列出:
- 新增文件
- 修改文件
- 删除文件
- 测试文件
要求:
不改变现有业务行为,
不新增第三方依赖,
保持现有调用兼容性。
先输出 Plan。25. 数据库变更 Plan 示例
数据库修改更应该先 Plan。
例如:
text
需求:
给 stake_order 增加 settlement_time。
当前阶段不要修改。
请先分析:
1. stake_order Entity
2. Mapper
3. Mapper XML
4. 所有 settlement_flag 使用位置
5. 结算任务
6. 查询接口
7. 统计代码
8. migration 规则
然后设计方案。
要求:
1. 不修改历史 migration
2. 新增独立 migration
3. 旧数据必须兼容
4. 分析 settlement_time 是否允许 null
5. 分析是否需要索引
6. 不删除现有 settlement_flag
7. 保持旧 API 兼容
最后给出:
数据库变更
Java 变更
测试方案
回滚风险
修改文件清单
不要修改代码。26. Bug Plan 和功能 Plan 不完全一样
新功能通常关注:
text
怎么实现Bug 更应该先关注:
text
根因是什么例如:
text
用户偶尔出现重复入账。
先不要修复。
请:
1. 找出所有入账入口
2. 找出 DepositRecord 状态变化
3. 找出余额更新方法
4. 找出定时任务是否可能重复执行
5. 找出 MQ / 重试机制
6. 找出唯一键
7. 找出事务边界
8. 找出幂等判断
要求:
先证明可能的重复入账路径。
不要直接增加 Redis 锁或数据库锁。
先输出:
根因假设
→ 代码证据
→ 复现路径
→ 修复方案
→ 测试方案这里特别重要的是:
text
不要先给解决方案
先找根因27. 性能优化 Plan 应该先找瓶颈
性能问题也不能直接:
text
帮我优化。应该:
text
分析接口响应慢的问题。
当前阶段不要修改代码。
请检查:
1. SQL 数量
2. 单条 SQL 执行方式
3. 是否 N+1
4. Redis
5. RPC
6. MQ
7. 循环
8. parallelStream
9. 大对象加载
10. 分页
11. 索引
12. 日志
先找出有代码证据的性能瓶颈。
按照:
P0
P1
P2
给出优化优先级。
不要在没有证据的情况下进行架构重构。Plan 的核心还是:
text
Evidence First28. Plan 不要写得过度复杂
Plan 很重要。
但也不能变成:
text
任何一个小修改
都先分析 30 分钟例如:
text
把 timeout 从 5 秒改成 10 秒如果位置已经明确:
text
直接改就可以。
可以简单按照风险分级。
低风险
text
拼写
变量名
简单配置
简单测试直接:
text
Implement中风险
text
单模块功能
Service 修改
接口逻辑
普通 Bug可以:
text
Quick Plan
→ Implement高风险
text
数据库
支付
钱包
认证
并发
架构
跨模块建议:
text
Explore
→ Detailed Plan
→ Review
→ Implement29. Plan 不是让 Codex 取代技术决策
还有一个误区:
text
既然 Codex 会 Plan,
那所有架构决策都让它决定。不应该。
更合理的是:
text
Codex
→ 搜索代码
→ 提取事实
→ 分析方案
→ 提醒风险
Developer
→ 结合业务
→ 做关键决策特别是:
text
数据库模型
资金安全
架构边界
兼容策略
生产风险最终仍然应该由开发者负责。
Plan 的价值是:
text
提高决策质量而不是:
text
取消人的决策30. Plan 和 AGENTS.md 怎么配合?
可以这样理解:
text
AGENTS.md
→ 长期项目规则
Prompt
→ 当前需求
Plan
→ 当前需求的实施方案例如:
text
AGENTS.md:
金额使用 BigDecimal
数据库必须 migration
禁止 git pushPrompt:
text
增加冻结余额功能Plan:
text
具体修改哪些表
哪些 Service
事务怎么设计
怎么保证幂等
怎么测试三者各自解决不同问题。
31. Plan 和 Prompt 的关系
上一篇我们总结:
text
Prompt
=
Context
+
Goal
+
Scope
+
Constraints
+
Verification
+
Output对于复杂任务,可以进一步变成:
text
Prompt
↓
Explore
↓
Plan
↓
Confirm
↓
Implement
↓
Verification
↓
Review所以 Plan 不是独立存在的。
它是:
text
复杂 Prompt进入实现之前的重要阶段。
32. 一个推荐的真实开发工作流
以后遇到复杂需求,可以固定使用:
text
① git status
↓
② codex
↓
③ /status
↓
④ 阅读 AGENTS.md
↓
⑤ 给出任务 Prompt
↓
⑥ Explore
↓
⑦ Impact Analysis
↓
⑧ Plan
↓
⑨ Developer Review Plan
↓
⑩ Implement
↓
⑪ Compile / Test
↓
⑫ Codex Review
↓
⑬ git diff
↓
⑭ Developer Review
↓
⑮ Commit这里最关键的变化就是:
text
需求和:
text
写代码之间多了一层:
text
Plan33. 最后怎么理解 Plan?
如果只记一句话:
text
Plan 的目的不是让 Codex 多说一点。
而是在代码真正被修改之前,
先暴露错误理解、遗漏范围和设计风险。简单任务:
text
Prompt
→ Implement复杂任务:
text
Prompt
→ Explore
→ Plan
→ Review
→ Implement尤其涉及:
text
Money
Database
Concurrency
Authentication
Architecture
Compatibility更应该:
text
Think Before Write最终可以把 Codex 的完整工作方式记成:
text
Read
↓
Understand
↓
Plan
↓
Implement
↓
Test
↓
Review其中:
text
Read
+
Understand
+
Plan解决的是:
text
做正确的事情而:
text
Implement
+
Test
+
Review解决的是:
text
把事情正确地做完当你开始真正使用这种方式以后,会发现 Coding Agent 的价值不再只是:
text
帮我快速生成代码而是:
text
帮助我完成一个完整的软件工程任务这才是 Plan First 真正重要的原因。
